package IC.SymbolTable;

import java.util.*;
import IC.SemanticCheckes.SemanticError;


public class BlockSymbolTable extends SymbolTable {

	public BlockSymbolTable(SymbolTable parent){
		this.InitSymbol(parent);
	}
	
	
	public VarSymbol getVarSymbol(String name, int line) throws SemanticError{
		VarSymbol vs = varEntries.get(name);
		if ( (line>0) && (vs != null)) {
			// defined later in the code
			if (vs.line > line)
				vs=null;
		}
		if (vs == null) {
			try{
				vs = ((BlockSymbolTable) parent).getVarSymbol(name, line);
			}catch (Exception e){
				throw new SemanticError("variable does not exist in block", name);
			}
			vs.isDefined = true;
		}
		return vs;
	}
	
	public ClassSymbolTable getEnclosingClassSymbolTable(){
		return ((BlockSymbolTable) parent).getEnclosingClassSymbolTable();
	}
	
	public void addVarSymbol(String name, String kind, String typeName, int line) throws SemanticError{
		this.varEntries.put(name, new VarSymbol(name, kind, typeName, line));
	}
	
	public void addBlockSymbolTable(BlockSymbolTable bst){
		blockSymbolTableEntries.add(bst);
	}
	
	public String toString(String path){
		String str = "Statement Block Symbol Table ( located in "+path+" )";
		
		// print local variables symbols list
		for(VarSymbol vs: varEntries.values()){
			str += "\n\tLocal variable: "+vs.getType().getName()+" "+vs.getName();
		}

		path = "statement block in "+path;
		
		// print children tables of block
		if(!blockSymbolTableEntries.isEmpty()){
			str += "\nChildren tables: ";
			for(BlockSymbolTable bst: blockSymbolTableEntries)
				str += "statement block in "+path+", ";
			str = str.substring(0, str.length()-2);
		}
		str += "\n\n";
		
		// print recursively all the block symbol tables
		for(BlockSymbolTable bst: blockSymbolTableEntries){
			str += bst.toString(path); // in BlockSymbolTable
		}
		
		return str;
	}
	
	public boolean isVarField (String name){
		if (varEntries.containsKey(name)) return false;
		else return ((BlockSymbolTable)parent).isVarField(name);
	}
	
	public int getVarDepthRec(String name){
		int vd = varEntries.containsKey(name) ? this.getDepth() :
			((BlockSymbolTable) parent).getVarDepthRec(name);
		return vd;
	}
	
	protected Map<String,VarSymbol> varEntries = new HashMap<String,VarSymbol>();
	protected List<BlockSymbolTable> blockSymbolTableEntries = new ArrayList<BlockSymbolTable>();
}
